#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use DBI;
use DBD::Pg;
use Digest::MD5 qw(md5_hex);
use Net::FTP;
use LWP::Simple;
use HTTP::Date;
use Carp;

#88888888888888888888888888888888888888888888888888888888888888888888888888888888

#	Usage

#88888888888888888888888888888888888888888888888888888888888888888888888888888888

my $usage = <<'USAGE';

USAGE:

    panda_load_sequence_sources.pl

    MANDATORY PARAMETERS:
                            --dbname STRING
                            --sequence_sources FILE

    OPTIONAL PARAMETERS:

                            [--verbose]
                            [--user STRING]         the postgreSQL user name.
                            [--host STRING]         the postgreSQL host name.
                            [--password STRING]     the postgreSQL password.
                            [--remove_first]        remove current entries first.

RESULTS:


   This script loads the sequence sources
   the sequences and accessions

USAGE


my $fields_usage = <<'USAGE';

	Sequence Sources File Format:
	
	1) Each Sequence Source Starts with a ">" (angle bracket)
						followed by an optional description
	
	2) Data for each sequence source can be specified in the following form
	FIELD=VALUE
	
	See the file sequence_source.README for more information on the
	data fields.

USAGE


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

#	Get options

#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
# mandatory
my $dbname 		= "";
my $sequence_sources= "";

# optional parameters
my $remove_first;
my $password		= "";
my $verbose			= 0;
my $help;
my $user			= "";
my $logfile			= "";
my $host			= "";

# as above but not user specifiable
my $panda_cmd_line	= "";

GetOptions(
			'dbname=s'			=> \$dbname,
			'sequence_sources=s'=> \$sequence_sources,
			'logfile=s'			=> \$logfile,
			'host=s'			=> \$host,
			'user=s'			=> \$user,
			'password=s'		=> \$password,
			'verbose'			=> \$verbose,
			'remove_first'		=> \$remove_first,
			'help'				=> \$help);

die $usage if ($help);
die ("\nERROR:\n\tMissing Argument: dbname\n$usage")
				unless ($dbname);
die ("\nERROR:\n\tMissing Argument: sequence_sources\n$usage")
				unless ($sequence_sources);
				

my %valid_values =
    (name                    => 1,
    description              => 1,
    depends                  => 1,
    remote_url               => 1,
    db_update_interval       => 1,
    local_file               => 1,
    check_up_to_date_cmds    => 1,
    pre_process_cmds         => 1,
    run_panda                => 1,
    panda_param_fasta_file   => 1,
    panda_param_regex        => 1,
    panda_param_db_name      => 1,
    panda_param_update_stats => 1,
    panda_param_misc         => 1,
    post_process_cmds        => 1);

sub enter_sequence_source_into_pandadb($\%)
{
	my ($dbh, $curr_values) = @_;
	$curr_values->{run_panda} = 'FALSE' if (!exists $curr_values->{run_panda});
	$curr_values->{panda_param_update_stats} = 'FALSE' if (!exists $curr_values->{panda_param_update_stats});
	for (qw(description
			depends
			remote_url
			db_update_interval
			local_file
			check_up_to_date_cmds
			pre_process_cmds
			panda_param_fasta_file
			panda_param_regex
			panda_param_db_name
			panda_param_update_stats
			panda_param_misc
			post_process_cmds))
	{
		if (!exists $curr_values->{$_})
		{
			$curr_values->{$_} = "";
		}
	}
	my $cnt_values = scalar keys %valid_values;
	my $sql = "INSERT INTO database_sources (".
				join (',', keys %valid_values).
				") VALUES (".
				join (',', ('?') x $cnt_values).
				");";

	$dbh->do($sql, undef,  @$curr_values{keys %valid_values})
		or die "Error\n\tCould not insert new values into PostgreSQL:\n[$sql]\n$cnt_values\n".
				$dbh->errstr;	

}


#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

#	Core logic!!

#88888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
#
# connect to database
#
my $dbihost = ($host) ? ";host=$host" : "";
my $dbh = DBI->connect( "dbi:Pg:dbname=$dbname$dbihost",
                        $user,
                        $password,
						{
                          RaiseError => 0,
                          AutoCommit => 0,
						  PrintError => 1
                        }
                      ) or
	die_source_database(undef, "connect to the database\n\t$DBI::errstr\n",
						undef, undef, undef);

#$dbh->begin_work();

open SEQSRC, $sequence_sources
		or die "Error\n\tCould not open the file [$sequence_sources]\n$@\n";


if ($remove_first)
{
	$dbh->do ("DELETE FROM database_sources;")
		or die "Could not remove obsolete entries from the database sources list.";
}
my %curr_values;
my $cnt_lines = 0;
my $rec_start = 1;
my $rec_name = 1;
while (<SEQSRC>)
{
	++$cnt_lines;

	chomp;

	#ignore comments or empty lines
	next if /^#/;
	next if /^\s*$/;

	# start of a new record
	if (/^>(.*)$/)
	{
		my $new_rec_name = $1;
		if (scalar keys %curr_values)
		{
			if (!exists $curr_values{name})
			{
				die "Error\n\tThe sequence source '$rec_name' beginning on line # does not ".
					"have a specified name.\n".
					"$fields_usage";
			}
			enter_sequence_source_into_pandadb($dbh, %curr_values);
			%curr_values = ();
		}
		$rec_start = $cnt_lines;
		$rec_name = $new_rec_name;
		next;
	}
	
	# do not allow wonky lines
	unless (/\s*([^=]+)\s*=\s*(.*)$/)
	{
		die "Error\n\tThe entry on line # $cnt_lines is non-conforming\n[$_]\n$fields_usage";
	}

	# do not allow invalid fields
	unless (exists $valid_values{lc $1})
	{
		die "Error\n\tThe entry on line # $cnt_lines is not one of the valid fields\n\t".
			'['. $_. "]\n\n$fields_usage\n";
	}
	
	# do not allow duplicate overriding values
	if (exists $curr_values{lc $1})
	{
		die "Error\n\tThe field on line # $cnt_lines has already been specified ".
			"for this sequence source\n".
			"$fields_usage";
	}

	$curr_values{lc $1} = $2 if (length $2);
}
if (scalar keys %curr_values)
{
	enter_sequence_source_into_pandadb($dbh, %curr_values);
}
$dbh->commit();
$dbh->disconnect();

